Vue实用

vue组件写法/*.vue文件 ; Vue.component(), props

vue实用

组件通信

### 1 一般父子组件。
1) 通过prop,和$emit $danghao:ContentNav 切换
2) parent/root,children 或者父组件中可以用 $refs调用子组件 $danghao:定时发布
如何实时响应?
如果修改父组件的值?

### 2 在有些情况下,我们可能需要对一个 prop 进行“双向绑定”
1) 为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:

.sync 修饰符的 v-bind 不能和表达式一起使用 $PS: 同v-model
将 v-bind.sync 用在一个字面量的对象上是无法正常工作的

2) 比如表单的数据v-model。定义表单自己的数据,然后在声明周期中把父组件的值赋给 表单自己定义的值 $danghao: ContenNav nav组件的active 值;帐号信息 申请描述

### 根/父组件 值为异步获取/更新
1) 如果要直接引用$root.$data.userInfo$root.userInfo, 属性的值,需要注意数据类型正确。不能直接给一个空值userInfo: {} 属性也需要赋值 user:{tags:[]},因为使用了tags的值
2) 如果可以确定 子组件 装载时,根组件的异步获取的数据已经成功,可以在子组件的生命周期中重新赋值
3) 通过watch 监听数据的变化

数据

  1. 拿到的值是 {__ob__: observer}。 无法取到里边的值,进行后续操作
    将返回的数据data先转换为JSON字符串形式,然后再从字符串形式转换成JSON格式JSON.parse(JSON.stringify(data))

  2. data下的字段无法通过表达式实现。所以只能通过条件判断了key === 'grade0' ? currWork_grade0 : currWork_grade1)[gkey].praiseCount
    为了减少嵌套,修改currWork_grade0.low 数据方便。 this.$set(this[currWork_${key}], gkey, data)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    data() {
    currWork_grade0: { low: {}, mid: {}, high: {} },
    currWork_grade1: { low: {}, mid: {}, high: {} },
    // 对比
    currWork: {
    currWork_grade0: { low: {}, mid: {}, high: {} },
    currWork_grade1: { low: {}, mid: {}, high: {} },
    }

    }
1
2
3
4
5
6
<div :class="['home-works-group-praise', (key === 'grade0' ? currWork_grade0 : currWork_grade1)[gkey].isPraise  && 'home-works-group-praise-light']">
<span>
<img @click="praise(gkey)" src="https://mr.xesimg.com/biz-growth-storage/activity/upload/20210324/0a32e1d885645f2c5d4b88a6d415f28b.png" alt="点赞">
<output>{{(key === 'grade0' ? currWork_grade0 : currWork_grade1)[gkey].praiseCount || 0 }}</output>
</span>
</div>

props

如果有多种类型,有几种写法。第二种写法可能eslint 规则校验不过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
props:{
selectionFixed: {
type: [String, Boolean],
default: ''
},
isIndex: {
type: Boolean,
default: false
},
indexFixed: {
type: String | Boolean,
default: ''
},
}

生命周期

accountCatMixin.js MIXIN:get cat - after || [{...}, {...}, {...}, __ob__: Observer] accountCatMixin.js MIXIN:get cat - after || [{...}, {...}, {...}, __ob__: Observer] accountMonthForm.vue Account: create|| [{...}, {...}, {...}, __ob__: Observer] 总结: -->虽然生命周期可以写asycn/await 但是并不会等待。而是直接进行其他的主任务,比如mouted 等。主任务完成,才是async 中的微任务
router: before router enter
生命周期(mixin -> 组件):before create -> created -> mounted
router: next(before router enter)
微任务:生命周期async 中的微任务执行,包括await及之后的 输出(此时才拿到接口中的数据)

beforeCreate 不能获取到this,包括this.methods调用

父子组件

父:before Create -> created -> before mounted
子:before Create -> created -> before mounted -> mounted
父:mounted

生命周期做了什么

事件

但是,如果是在自己封装的组件或者是使用一些第三方的UI库时,会发现并不起效果,这时就需要用到.native修饰符了
如果遇到.native修饰符也无效的情况,可能就需要用到$listeners

请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCode:keyup.17。

1
2
3
4
5
6
7
8
<!-- 按下Alt + 释放C触发 -->
<input @keyup.alt.67="clear">

<!-- 按下Alt + 释放任意键触发 -->
<input @keyup.alt="other">

<!-- 按下Ctrl + enter时触发 -->
<input @keydown.ctrl.13="submit">

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

其它

1) 为什么组件data是一个函数?多个/不同实例间 不共用相同的数据
2)data:组件数据。
computed:根据data或者其他数据 过滤的数据,可以缓存,只要源数据发生变动。
也可以有set方法

计算属性是基于它们的响应式依赖进行缓存的
method: 每次调用都会执行。如果你不希望有缓存,请用方法来替代。
watch(侦听属性): 数据变化时执行异步或开销较大的操作时

3) watch: 不能用箭头函数,否则this无法绑定到当前组件。

refs

  1. v-for 循环中动态绑定ref。 实际得到是一个数组,如需使用
    在vue组件的v-for循环中是无法动态绑定ref的,若强行绑定,当访问的时候会出现 undefined 的结果,但这不是说没有解决方法,在循环中写:ref=”xxx”,循环结束后,实际生成的是一个ref数组,当取循环中某一元素的ref时,使用下标即可,见下例:
    1
    2
    3
    4
    5
    6
    7
    <!-- template -->
    <li v-for="(list, index) in tagList" :key="index" ref="tagItem">{{list.value}}</li>
    <li v-for="(list, index) in tagList" :key="index" :ref="index">{{list.value}}</li>

    <!-- script -->
    this.$refs.tagItem[0].style.backgroundImage = `url(${xxx})`
    this.$refs[index][0] // 动态 通过数组下标0

当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们- 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。

函数式组件

Vue 提供了一种称为函数式组件的组件类型,用来定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props 来显示组件。

1
2
3
4
5
6
7
8
9
10
11
12
Vue.component('my-component', {
functional: true,
// Props 是可选的
props: {
// ...
},
// 为了弥补缺少的实例
// 提供第二个参数作为上下文
render: function (createElement, context) {
// ...
}
})

或者单文件定义函数式组件(2.5版本后)

1
2
3
4
5
6
7
8
9
<template functional>
<button
class="btn btn-primary"
v-bind="data.attrs"
v-on="listeners"
>
<slot/>
</button>
</template>

三:和正常自定义组件的区别?
不维护响应数据
无钩子函数
没有instance实例。所以在组件内部没有办法像传统组件一样通过this来访问组件属性

正是因为函数式组件精简了很多例如响应式和钩子函数的处理,因此渲染性能会有一定的提高,
所以如果你的业务组件是一个纯展示且不需要有响应式数据状态的处理的,那函数式组件会是一个非常好的选择。

四:render函数

render函数是函数式组件最重要的参数,且是必须的。
render函数有两个参数,一个是createElement,一个是context

JSX

如果你写了很多渲染函数,可能会觉得下面这样的代码写起来很痛苦
有一个 Babel 插件,用于在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上。

es模块使用

1. es模块使用。兼容回退

# Vue中的新功能:ES模块浏览器生成

1
2
3
<script type="module" src="vue.mjs"></script>
<script type="module" src="app.js"></script>
<script nomodule src="/dist/build.js"></script> <!--Fallback-->

app.js

1
2
3
4
5
6
7
8
import Vue from './vue.mjs';

new Vue({
el: '#app',
data: {
message: 'Hello Vue 2.6.0-beta1 ESM Browser Build!'
}
});

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
entry: './app.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
// add Babel here if needed
},
resolve: {
alias: {
'./vue.js': './node_modules/vue/dist/vue.esm.browser.js'
}
}
};

1. 也可以从vue的components中导出具体的某一个方法。(非mixin方法)

使用的时候,要注意绑定this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* sharePanel.vue */
const app = {
name: 'sharePanel',
mixin: [],
data() {
return {}
},
methods: {
handleShareClick() {

}
}
}
export default app
const shareClick = app.methods.handleShareClick
export { shareClick }

/* home.vue */
import sharePanel, { shareClick } from 'components/sharePanel'
export default {
name: 'Home',
data() {
return {}
},
mounted() {
shareClick.bind(this, 'wechat')
}
}

骨架屏

vue-loader

2018.11.21

dev-tools

不生效Vue.js Devtools inspection is not available because it's in production mode or explicitly disabled
vue不是生成环境或压缩版的

1
2
3
if(process.env.NODE_ENV === 'development'){
Vue.config.devtools = true
}

vue-cli

vue-cli实用

element ui

element-ui 实践

swiper

swiper/vue

swiper文档: https://swiperjs.com/get-started

<!–
移动端滑动不流畅:
observer: true,//修改swiper自己或子元素时,自动初始化swiper
observeParents: true,//修改swiper的父元素时,自动初始化swiper
包括动态生产的swiper, 隐藏后出现。
多个swiper插件,出现混乱问题: 1. 实例化swiper时加上其父元素加以区分; 2.Swiper加上ID或Class区分,要保留默认的类名swiper-container

swiper.js 碰到的坑
关于swiper移动端的坑
为了提高移动端的加载速度,开发人员手动拿出需要的siwper的样式和js是ok的,
但是这里需要需要注意几点:
移动端上的卡顿问题:如果只引用了swiper的js而没有引入swiper.css和swiper.animate.js,移动端就会出现卡顿问题
官方建议代码: observer,observeParents。
–>

Swiper Vue.js Components: https://swiperjs.com/vue#virtual-slides
如果只有一个可以把事件监听写在swiper上。否则需要利用this.$refs.swiper1 获取到swiper实例及其index

Swiper Vue.js components are compatible only with new Vue.js version 3
swiper/vue exports 2 components: Swiper and SwiperSlide:

vue-awesome-swiper

vue-awesome-swiper:https://github.com/surmon-china/vue-awesome-swiper/

  1. 属性和事件监听 通过属性配置。
  2. 事件。也可以在组件上写事件监听,但是有的事件好像没有(和swiper文档有出入)。
    而且函数回调中参数:swiper并没有。所以只能写在on中监听(注意this)
  3. 属性。slidesPerView 会自动计算宽度根据屏幕,所以不能设置slide的宽度。
    需要把值改为 auto。通过css调整宽度
  4. 如果要居中对齐,且中间内容放大。可以通过设置centeredSlides
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
swiperOptions: {
// autoplay: {
// delay: 3000, //3秒切换一次
// disableOnInteraction: false, //鼠标拖动后继续自动轮播
// },
// width: 300,
// slidesPerView : 3,
slidesPerView: 'auto',
centeredSlides: true,
// spaceBetween: 10,
// effect: 'fade'
on: {
slideChange: function(swiper){
// console.log('过渡结束');
console.log('过渡结束', swiper, this.$el[0], this.activeIndex)
const dom = this.$el[0]
const gkey = dom.dataset.gkey
_that.changeSlide(gkey, this.activeIndex)
},
// slideChangeEnd: function(swiper){
// console.log('过渡结束', swiper);
// }
}
},

2019.4.14 星期日 17:30

vuex

Vuex:https://vuex.vuejs.org/zh/
## 一 安装
Vuex 依赖 Promise。如果你支持的浏览器并没有实现
## 二 vuex是什么

Flux 架构就像眼镜:您自会知道什么时候需要它。
状态管理模式:state,view,action
### 三 开始
## 四 核心概念
State:单一状态树(可module)。唯一数据源。多实例也可返回函数,相当与vue的data
Getter:相当与vue的计算属性,可缓存。可通过属性和方法访问
Mutation:可直接修改State,不能使用异步 。可用常量来管理所有事件类型,
Action:提交mutation非直接修改状态 ,可以包含异步。 可以多个异步组合
Module: 多种便捷方式,可以减少命名空间的书写

辅助函数 和 对象展开运算符 :...mapState,...mapGetters,...mapMutations,...mapActions
## 五 项目结构
根目录下可index 和根级别的action,mutation,module

## 六 插件 $Skip

## 七 严格模式
strict: true.生产时要去掉
## 八 表单处理
当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model 会比较棘手: 在严格模式中,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。

另一个方法是使用带有 setter 的双向绑定计算属性:

## 测试 $Skip
## 热重载 $Skip

vue-router

  1. vue-router url参数问题。 哈希qurey 和 路由query
    activity/#/sharePage?env=sandbox: hash search。可以通过 this.$route.query 获取到
    而且href.search 是空的
    activity/?source=h5&from=app#/sharePage: url search。 不可以通过 route 获取。

问题

安装问题

#### TypeError: Cannot read property ‘parseComponent‘ of undefined
原因:是vue-template-compiler 升级版本后 parseComponent函数已被删除,导致 component-compiler-utils报错。

npm uninstall @vue/component-compiler-utils
npm install –dev @vue/component-compiler-utils@3.1.2

#### vue项目中使用/deep/报错
方法:降低sass-loader版本

npm uninstall sass-loader
npm install sass-loader@7.0.0
npm install node-sass

#### core-js 报错
core-js/modules/es6.array.find-index in

core-js版本太高
npm install core-js@2

element

#### Uncaught ReferenceError: element is not defined
cdn 方式引入element ui

1
2
3
4
5
6
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'axios':'axios',
'element-ui': 'ELEMENT', // 之前是 ElementUI
}
1
2
3
import { Message } from 'element-ui'
// 或者
const { Message } = ELEMENT
knowledge is no pay,reward is kindness
0%